#include "lightingui.h"
#include "ui_lightingui.h"
#include "infoui.h"
#include "constants.h"
#include "paramui.h"
#include "infoui.h"
#include "log4z.h"
#include "controller.h"
#include <QMessageBox>
#include <QBitmap>
#include <QTimer>

bool bDoneBeep = true;
void* doneBeep(void* ptr)
{
    LOGD("Done beep enter!");
    QThread::msleep(500);

    bool bNormalLight = true;
    LightingUI* lgUi = (LightingUI*) ptr;
    if (0 != lgUi)
    {
        if (lgUi->getLightErr() != 0)
        {
            bNormalLight = false;
        }
    }
    if (bNormalLight)
    {
        //beeper 5 times
        int i = 0;
        while (i++<5 && bDoneBeep)
        {
            system("echo 1 > /sys/class/gpio/gpio113/value");
            system("echo 1 > /sys/class/gpio/gpio112/value");
            QThread::msleep(1500);
            system("echo 0 > /sys/class/gpio/gpio113/value");
            system("echo 0 > /sys/class/gpio/gpio112/value");
            QThread::msleep(500);
        }
        while (bDoneBeep)
        {
            system("echo 1 > /sys/class/gpio/gpio112/value");
            QThread::msleep(500);
            system("echo 0 > /sys/class/gpio/gpio112/value");
            QThread::msleep(500);
        }
    }
    else
    {
        system("echo 0 > /sys/class/gpio/gpio112/value");
        //beeper 5 times
        int i = 0;
        while (i++<5 && bDoneBeep)
        {
            system("echo 1 > /sys/class/gpio/gpio113/value");
            system("echo 1 > /sys/class/gpio/gpio111/value");
            QThread::msleep(1500);
            system("echo 0 > /sys/class/gpio/gpio113/value");
            system("echo 0 > /sys/class/gpio/gpio111/value");
            QThread::msleep(500);
        }
        while (bDoneBeep)
        {
            system("echo 1 > /sys/class/gpio/gpio111/value");
            QThread::msleep(500);
            system("echo 0 > /sys/class/gpio/gpio111/value");
            QThread::msleep(500);
        }
    }
    system("echo 0 > /sys/class/gpio/gpio111/value");
    system("echo 1 > /sys/class/gpio/gpio112/value");
}

void* sendPause(void* ptr)
{
    LightingUI* lu = (LightingUI*)ptr;
    if (0 != lu)
    {
        lu->onLightResume();
    }
}

LightingUI::LightingUI(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::LightingUI),
    lpThread(0),
    bLightingFlag(false),
    bShutdownFlag(false),
    bErrFlag(false),
    bPauseFlag(true),
    bBtnPressed(false),
    iErrRepeatTimes(new int[10]),
    iLightErr(0)
{
    ui->setupUi(this);
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint );
    //load logo and background
    QPixmap lg(logoStr);
    ui->logo->setPixmap(lg);
    ui->lgtLogo->setPixmap(QPixmap(lightStr));

    QPixmap bg(backgroundStr);
    QPalette background;
    background.setBrush(QPalette::Background, QBrush(bg));
    setPalette(background);
    QPalette palette = ui->data->palette();
    palette.setColor(backgroundRole(), QColor(255,255,255));
    ui->data->setPalette(palette);
    ui->data->setAutoFillBackground(true);
    QPalette tltP = ui->titleFrm->palette();
    tltP.setColor(backgroundRole(), QColor(195,234,246));
    ui->titleFrm->setPalette(tltP);
    palette.setColor(backgroundRole(), Qt::lightGray);
    ui->titleFrm->setPalette(palette);
    ui->titleFrm->setAutoFillBackground(true);
    //set font color
    QPalette pe;
    pe.setColor(QPalette::WindowText,Qt::white);
    ui->cTime->setPalette(pe);
    ui->btnCnl->setPalette(pe);
    ui->btnPause->setPalette(pe);
    ui->btnRet->setPalette(pe);
    //button style
    QPalette btnPe;
    btnPe.setColor(QPalette::ButtonText, Qt::white);
    ui->btnPause->setStyleSheet(blueBtn);
    ui->btnCnl->setStyleSheet(greenBtn);
    ui->btnRet->setStyleSheet(greenBtn);
    ui->btnPause->setPalette(btnPe);
    ui->btnCnl->setPalette(btnPe);
    ui->btnRet->setPalette(btnPe);
    //line edit
    ui->tDianya->setStyleSheet("QLineEdit {border:1px solid "
                               ";background-color:rgb(211,211,211);border-radius:5px;selection-color:pink}");
    ui->tMaikuan->setStyleSheet("QLineEdit {border:1px solid "
                               ";background-color:rgb(211,211,211);border-radius:5px;selection-color:pink}");
    ui->tCishu->setStyleSheet("QLineEdit {border:1px solid "
                               ";background-color:rgb(211,211,211);border-radius:5px;selection-color:pink}");
    ui->tJiange->setStyleSheet("QLineEdit {border:1px solid "
                               ";background-color:rgb(211,211,211);border-radius:5px;selection-color:pink}");
    ui->tLiusu->setStyleSheet("QLineEdit {border:1px solid "
                               ";background-color:rgb(211,211,211);border-radius:5px;selection-color:pink}");
    ui->tYaodong->setStyleSheet("QLineEdit {border:1px solid "
                                ";background-color:rgb(211,211,211);border-radius:5px;selection-color:pink}");
    QTimer *upTime = new QTimer(this);
    connect(upTime,SIGNAL(timeout()),this,SLOT(updateTime()));
    updateTime();
    upTime->start(1000);
    connect(this, SIGNAL(lightDone(int)), this, SLOT(onLightDone(int)));
    //connect(this, SIGNAL(lightShutdown()), this, SLOT(onLightResume()));
    lpThread = new LightProcesser(this);
    connect(lpThread, SIGNAL(statusChange(int)), SLOT(onStatusChange(int)));
    //Disable cancel and pause buttons
    ui->btnCnl->setEnabled(false);
    ui->btnPause->setEnabled(false);
    //
    initRepeatTimes();
}

LightingUI::~LightingUI()
{
    delete ui;
    delete lpThread;
    if (0 != iErrRepeatTimes)
    {
        delete iErrRepeatTimes;
    }
}

void LightingUI::shutdownAll()
{
    if (bShutdownFlag) return;
    bShutdownFlag = true;
    LOGFMTD("Func %s, shutdown all staffs", __func__);
    //Exit thread
    lpThread->quitLight(false);
    //Wait thread terminate
    while(!lpThread->isFinished())
    {
        lpThread->quitLight(false);
        LOGD("Light thread still runnning");
        QThread::msleep(200);
    }
    LOGD("Now stop light, rudong, motor, yaodong, door...");
    Controller gEttaCtrl;
    int iRet = gEttaCtrl.StopLight();
    gEttaCtrl.StopRuDong();
    gEttaCtrl.StopMotor();
    //Default the dianjiguan
    int iSt = gEttaCtrl.StartIo();
    int iTot = 0;
    if (iSt == 1)
    {
        //guiwei
        gEttaCtrl.SpeedMotor(1);
        gEttaCtrl.StartMotor();
        while (iSt == 1 && iTot++ <= 20)
        {
            QThread::msleep(200);
            iSt = gEttaCtrl.StartIo();
        }
        gEttaCtrl.StopMotor();
    }
    gEttaCtrl.CloseYao();
    if (iRet == -1)
    {
        //retry one time
        QThread::msleep(200);
        gEttaCtrl.StopLight();
    }
    gEttaCtrl.OpenDoor();
}

void LightingUI::initRepeatTimes()
{
    for (int i=0; i<10; i++)
    {
        if (iErrRepeatTimes != 0)
        {
            iErrRepeatTimes[i] = 0;
        }
    }
}

void LightingUI::on_btnCnl_clicked()
{
    InfoUI ifu;
    ifu.QuestionDialog();
    ifu.SetInfo(tr("Cancel"), tr("Cancel operation?"));
    int iRet = ifu.exec();
    if (iRet == 1)
    {
        //Error happen, not show any thing
        if (bErrFlag) return;
        bLightingFlag = false;
        //Stop all
        ui->lhtLbl->setText(tr("Operation cancelled"));
        ui->btnRet->show();
        ui->btnCnl->hide();
        ui->btnPause->hide();
        QPalette tltP = ui->titleFrm->palette();
        tltP.setColor(backgroundRole(), QColor(251,225,226));
        ui->titleFrm->setPalette(tltP);
        ui->lgtLogo->setPixmap(QPixmap(cancelStr));
        shutdownAll();
    }
}

void LightingUI::updateTime()
{
    QDateTime curTime = QDateTime::currentDateTime();
    QString lblTm = curTime.date().toString("yyyy/MM/dd") + "\n " + curTime.time().toString("hh:mm:ss");
    ui->cTime->setText(lblTm);
    //update light time
    if (bLightingFlag)
    {
        QString lightTm = QString(tr("Starting time %1, Elapsed time %2 min")).arg(qdtStart.time().toString("hh:mm:ss"))
                .arg(qdtStart.secsTo(curTime)/60);
        ui->lblTm->setText(lightTm);
    }
}

void LightingUI::on_btnPause_clicked()
{
    if (bBtnPressed)
    {
        return;
    }
    ui->btnPause->setEnabled(false);
    bBtnPressed = true;
    if (bPauseFlag)
    {
        ui->lhtLbl->setText(tr("Operation paused"));
        ui->btnPause->setText(tr("Continue"));
        QPalette tltP = ui->titleFrm->palette();
        tltP.setColor(backgroundRole(), QColor(249,232,183));
        ui->titleFrm->setPalette(tltP);
        ui->lgtLogo->setPixmap(QPixmap(pauseStr));

        pthread_t pause_tid;
        pthread_create(&pause_tid, NULL, sendPause, this);
    }
    else
    {
        ui->lhtLbl->setText(tr("Operating, please wait"));
        ui->btnPause->setText(tr("Pause"));
        QPalette tltP = ui->titleFrm->palette();
        tltP.setColor(backgroundRole(), QColor(195,234,246));
        ui->titleFrm->setPalette(tltP);
        ui->lgtLogo->setPixmap(QPixmap(lightStr));
        //start light
        if (lpThread != 0)
        {
            LOGFMTD("Func %s: Resume light", __func__);
            lpThread->start();
        }
        bLightingFlag = true;
        bShutdownFlag = false;
        bErrFlag = false;
        bPauseFlag = !bPauseFlag;
        bBtnPressed = false;
    }
}

void LightingUI::getShow()
{
    if (lpThread != 0)
    {
        LOGFMTD("Func %s: Show lighting UI", __func__);
        lpThread->start();
    }
    bLightingFlag = true;
    bShutdownFlag = false;
    bErrFlag = false;
    qdtStart = QDateTime::currentDateTime();
    //Disable cancel and pause buttons
    ui->btnCnl->setEnabled(false);
    ui->btnPause->setEnabled(false);
    ui->lhtLbl->setText(tr("Operating, please wait"));
    ui->btnPause->setText(tr("Pause"));
    QPalette tltP = ui->titleFrm->palette();
    tltP.setColor(backgroundRole(), QColor(195,234,246));
    ui->titleFrm->setPalette(tltP);
    ui->lgtLogo->setPixmap(QPixmap(lightStr));
    ui->btnRet->hide();
    ui->btnCnl->show();
    ui->btnPause->show();
    show();
    activateWindow();
    raise();
    //set value
    ui->tDianya->setText(ParamUI::qstrDianya);
    ui->tMaikuan->setText(ParamUI::qstrMaikuan);
    ui->tCishu->setText(ParamUI::qstrCishu);
    ui->tJiange->setText(ParamUI::qstrJiange);
    ui->tLiusu->setText(ParamUI::qstrLiusu);
    if (ParamUI::blYaodong)
    {
        ui->tYaodong->setText(tr("On"));
    }
    else
    {
        ui->tYaodong->setText(tr("Off"));
    }
}

void LightingUI::onLightDone(int iRet)
{
    bLightingFlag = false;
    bDoneBeep = true;
    iLightErr = iRet;
    if (iRet == 0)
    {
        ui->lhtLbl->setText(tr("Operation accomplished"));
        QPalette tltP = ui->titleFrm->palette();
        tltP.setColor(backgroundRole(), QColor(199,234,208));
        ui->titleFrm->setPalette(tltP);
        ui->lgtLogo->setPixmap(QPixmap(doneStr));
    }
    else
    {
        ui->lhtLbl->setText(tr("Operation failed"));
        QPalette tltP = ui->titleFrm->palette();
        tltP.setColor(backgroundRole(), QColor(251,225,226));
        ui->titleFrm->setPalette(tltP);
        ui->lgtLogo->setPixmap(QPixmap(cancelStr));
    }
    ui->btnRet->show();
    ui->btnCnl->hide();
    ui->btnPause->hide();

    QDateTime curTime = QDateTime::currentDateTime();
    QString lightTm = QString(tr("Starting time %1, Ending time %2, Elapsed time %3 min")).arg(qdtStart.time().toString("hh:mm:ss")).
                               arg(curTime.time().toString("hh:mm:ss")).arg(qdtStart.secsTo(curTime)/60);
    ui->lblTm->setText(lightTm);

    pthread_t led_tid;
    pthread_create(&led_tid, NULL, doneBeep, this);
}

void LightingUI::on_btnRet_clicked()
{
    bDoneBeep = false;
    hide();
    emit retMain();
}

void LightingUI::onStatusChange(int iv)
{
    int iTmpValue = 0;
    if (iv == 8001)
    {
        iTmpValue = iErrRepeatTimes[0];
        iTmpValue++;
        initRepeatTimes();
        iErrRepeatTimes[0] = iTmpValue;
        //8005
        if (iTmpValue >= 3)
        {
            bErrFlag = true;
            shutdownAll();
            hide();
            emit sendErr(tr("Error code: 0x8005\n----Door error"));
            return;
        }
        else
        {
            bErrFlag = true;
            shutdownAll();
            InfoUI ifu;
            ifu.InfoDialog();
            ifu.SetInfo(tr("Error"), tr("Door error!"));
            ifu.exec();
            hide();
            emit retMain();
            return;
        }
    }
    else if (iv == 8002)
    {
        initRepeatTimes();
        bErrFlag = true;
        shutdownAll();
        InfoUI ifu;
        ifu.InfoDialog();
        ifu.SetInfo(tr("Error"), tr("Pipeline error!"));
        ifu.exec();
        hide();
        emit retMain();
        return;
    }
    else if (iv == 8003)
    {
        iTmpValue = iErrRepeatTimes[2];
        iTmpValue++;
        initRepeatTimes();
        iErrRepeatTimes[2] = iTmpValue;
        //8001
        if (iTmpValue >= 3)
        {
            bErrFlag = true;
            shutdownAll();
            hide();
            emit sendErr(tr("Error code: 0x8001\n----Communication error!"));
            return;
        }
        else
        {
            bErrFlag = true;
            shutdownAll();
            InfoUI ifu;
            ifu.InfoDialog();
            ifu.SetInfo(tr("Error"), tr("Communication error!"));
            ifu.exec();
            hide();
            emit retMain();
            return;
        }
    }
    else if (iv == 8004)
    {
        iTmpValue = iErrRepeatTimes[3];
        iTmpValue++;
        initRepeatTimes();
        iErrRepeatTimes[3] = iTmpValue;
        //8004
        if (iTmpValue >= 3)
        {
            bErrFlag = true;
            shutdownAll();
            hide();
            emit sendErr(tr("Error code: 0x8004\n----Shaker error!"));
            return;
        }
        else
        {
            bErrFlag = true;
            shutdownAll();
            InfoUI ifu;
            ifu.InfoDialog();
            ifu.SetInfo(tr("Error"), tr("Shaker error!"));
            ifu.exec();
            hide();
            emit retMain();
            return;
        }
        //8004
    }
    else if (iv == 8005)
    {
        iTmpValue = iErrRepeatTimes[4];
        iTmpValue++;
        initRepeatTimes();
        iErrRepeatTimes[4] = iTmpValue;
        //8009
        if (iTmpValue >= 3)
        {
            bErrFlag = true;
            shutdownAll();
            hide();
            emit sendErr(tr("Error code: 0x8009\n----Fluid-detector error!"));
            return;
        }
        else
        {
            bErrFlag = true;
            shutdownAll();
            InfoUI ifu;
            ifu.InfoDialog();
            ifu.SetInfo(tr("Error"), tr("Fluid-detector error!\n1. Please check peristaltic pump.\n2. Please check pipeline connection."));
            ifu.exec();
            hide();
            emit retMain();
            return;
        }
    }
    else if (iv == 8006)
    {
        iTmpValue = iErrRepeatTimes[5];
        iTmpValue++;
        initRepeatTimes();
        iErrRepeatTimes[5] = iTmpValue;
        //8010
        if (iTmpValue >= 3)
        {
            bErrFlag = true;
            shutdownAll();
            hide();
            emit sendErr(tr("Error code: 0x8010\n----Strike termination error!"));
            return;
        }
        else
        {
            bErrFlag = true;
            shutdownAll();
            InfoUI ifu;
            ifu.InfoDialog();
            ifu.SetInfo(tr("Error"), tr("Strike termination error!"));
            ifu.exec();
            hide();
            emit retMain();
            return;
        }
        //8010

    }
    else if (iv == 8007)
    {
        iTmpValue = iErrRepeatTimes[6];
        iTmpValue++;
        initRepeatTimes();
        iErrRepeatTimes[6] = iTmpValue;
        //8003
        if (iTmpValue >= 3)
        {
            bErrFlag = true;
            shutdownAll();
            hide();
            emit sendErr(tr("Error code: 0x8003\n----Rotating motor error!"));
            return;
        }
        else
        {
            bErrFlag = true;
            shutdownAll();
            InfoUI ifu;
            ifu.InfoDialog();
            ifu.SetInfo(tr("Error"), tr("Rotating motor error!"));
            ifu.exec();
            hide();
            emit retMain();
            return;
        }
    }
    else if (iv == 8011)
    {
        initRepeatTimes();
        bErrFlag = true;
        shutdownAll();
        InfoUI ifu;
        ifu.InfoDialog();
        ifu.SetInfo(tr("Error"), tr("No pipeline!"));
        ifu.exec();
        hide();
        emit retMain();
        return;
    }
    else if (iv == 8012)
    {
        iTmpValue = iErrRepeatTimes[8];
        iTmpValue++;
        initRepeatTimes();
        iErrRepeatTimes[8] = iTmpValue;
        //8006
        if (iTmpValue >= 3)
        {
            bErrFlag = true;
            shutdownAll();
            hide();
            emit sendErr(tr("Error code: 0x8006\n----High voltage power supply error!"));
            return;
        }
        else
        {
            bErrFlag = true;
            shutdownAll();
            InfoUI ifu;
            ifu.InfoDialog();
            ifu.SetInfo(tr("Error"), tr("High voltage power supply error!"));
            ifu.exec();
            hide();
            emit retMain();
            return;
        }
    }
    else if (iv == 8013)
    {
        iTmpValue = iErrRepeatTimes[9];
        iTmpValue++;
        initRepeatTimes();
        iErrRepeatTimes[9] = iTmpValue;
        //8007
        if (iTmpValue >= 3)
        {
            bErrFlag = true;
            shutdownAll();
            hide();
            emit sendErr(tr("Error code: 0x8007\n----IGBT error!"));
            return;
        }
        else
        {
            bErrFlag = true;
            shutdownAll();
            InfoUI ifu;
            ifu.InfoDialog();
            ifu.SetInfo(tr("Error"), tr("IGBT error!"));
            ifu.exec();
            hide();
            emit retMain();
            return;
        }
    }
    else if (iv == 8014)
    {
        iTmpValue = iErrRepeatTimes[1];
        iTmpValue++;
        initRepeatTimes();
        iErrRepeatTimes[1] = iTmpValue;
        //8008
        if (iTmpValue >= 3)
        {
            bErrFlag = true;
            shutdownAll();
            hide();
            emit sendErr(tr("Error code: 0x8008\n----Strike error!"));
            return;
        }
        else
        {
            bErrFlag = true;
            shutdownAll();
            InfoUI ifu;
            ifu.InfoDialog();
            ifu.SetInfo(tr("Error"), tr("Strike error!"));
            ifu.exec();
            hide();
            emit retMain();
            return;
        }

    }
    else if (iv == 0)
    {
        initRepeatTimes();
        emit lightDone(0);
    }
    else if (iv == 8010)
    {
        initRepeatTimes();
        emit lightDone(1);
    }
    else if (iv == 1)
    {
        //Enable cancel and pause buttons
        LOGD("Enable pause and cancel!");
        ui->btnCnl->setEnabled(true);
        ui->btnPause->setEnabled(true);
    }
}

void LightingUI::onShutdown()
{
    //exit
    if (0 != lpThread)
    {
        lpThread->quitLight(false);
    }
}

void LightingUI::onLightResume()
{
    shutdownAll();
    ui->btnPause->setEnabled(true);
    bPauseFlag = !bPauseFlag;
    bBtnPressed = false;
}

int LightingUI::getLightErr()
{
    return iLightErr;
}
